<?php

declare(strict_types=1);
/**
 * This file is part of Hyperf.
 *
 * @link     https://www.hyperf.io
 * @document https://hyperf.wiki
 * @contact  group@hyperf.io
 * @license  https://github.com/hyperf/hyperf/blob/master/LICENSE
 */

namespace App\Utils;

use GuzzleHttp\Exception\GuzzleException;
use Hyperf\Coroutine\Coroutine;
use Hyperf\Guzzle\ClientFactory;
use Hyperf\Logger\LoggerFactory;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\ContainerInterface;
use Psr\Container\NotFoundExceptionInterface;
use stdClass;

class LiveApi
{
    protected $gateway = 'https://zzzb436.app';
    protected $gatewayGroup = [];

    protected $client;

    protected float $requestDelayTime = 0;

    protected int $httpErrorDelayMultiplication = 10;
    protected bool $lastRequestHttpError = false;

    protected $headers = [
        'content-type' => 'application/json;charset=UTF-8',
        'User-Agent' => 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36',
    ];
    protected $logger;

    public function __construct(protected ContainerInterface $container, $gateway = '', $requestDelayTime = 0)
    {
        try {
            $this->setGateway($gateway);
            $this->setRequestDelayTime($requestDelayTime);
            $this->client = $this->container->get(ClientFactory::class)->create();
            $this->logger = $this->container->get(LoggerFactory::class)->get('SyncMatchStatsTask', 'default');
        } catch (NotFoundExceptionInterface|ContainerExceptionInterface $e) {
        }
    }

    /**
     * 设置请求延迟时间
     * @param $time
     * @return void
     */
    public function setRequestDelayTime($time): void
    {
        $this->requestDelayTime = $time;
    }

    /**
     * 设置API网关.
     * @param mixed $gateway
     */
    public function setGateway($gateway): void
    {
        if (strpos($gateway, '|')) {
            $this->gatewayGroup = array_merge($this->gatewayGroup, array_unique(array_filter(explode('|', $gateway))));
        } elseif(str_starts_with($gateway, 'http')) {
            $this->gatewayGroup[] = $gateway;
        }
    }

    /**
     * 获取比赛列表.
     * @param mixed $pageNum
     * @param int $pageSize
     * @param array $query
     * @return array|false|mixed|stdClass
     */
    public function getMatchList($pageNum, $pageSize = 200, $query = []): mixed
    {
        $data = [
            'pageNum' => $pageNum,
            'pageSize' => $pageSize,
            'query' => [
                'sportId' => $query['sportId'] ?? 0,
                'videoStatus' => $query['videoStatus'] ?? null,
                'searchWord' => $query['searchWord'] ?? null,
                'time' => $query['time'] ?? '',
            ],
        ];
        return $this->_request('POST', '/business/web_race/match_list', $data);
    }

    /**
     * 获取比赛信息.
     * @param mixed $matchId
     * @return array|false|mixed|stdClass
     */
    public function getMatchInfo($matchId): mixed
    {
        return $this->_request('POST', '/business/match/match_info', ['matchId' => $matchId]);
    }

    /**
     * 获取比赛ODDS.
     * @param mixed $matchId
     * @return array|false|mixed|stdClass
     */
    public function getMatchOdds($matchId): mixed
    {
        return $this->_request('POST', '/business/match/match_odds', ['matchId' => $matchId]);
    }

    /**
     * 获取比赛文字直播.
     * @param mixed $matchId
     * @return array|false|mixed|stdClass
     */
    public function getMatchTextLives($matchId): mixed
    {
        return $this->_request('POST', '/business/match/match_text_lives', ['matchId' => $matchId]);
    }

    /**
     * 获取比赛状态信息.
     * @param mixed $matchId
     * @return array|false|mixed|stdClass
     */
    public function getMatchStats($matchId): mixed
    {
        return $this->_request('POST', '/business/match/match_stats', ['matchId' => $matchId]);
    }

    /**
     * 获取比赛趋势数据
     * @param $matchId
     * @return array|false|mixed|stdClass
     */
    public function getMatchTrend($matchId): mixed
    {
        return $this->_request('POST', '/business/match/match_trender', ['matchId' => $matchId]);
    }

    /**
     * 获取比赛阵容
     * @param $matchId
     * @return array|false|mixed|stdClass
     */
    public function getMatchLineup($matchId): mixed
    {
        return $this->_request('POST', '/business/match/match_lineup', ['matchId' => $matchId]);
    }

    /**
     * 获取比赛重要事件 足球
     * @param $matchId
     * @return array|false|mixed|stdClass
     */
    public function getMatchIncidents($matchId): mixed
    {
        return $this->_request('POST', '/business/match/match_incidents', ['matchId' => $matchId]);
    }

    /**
     * 获取比赛球队统计
     * @param $matchId
     * @return mixed
     */
    public function getMatchTeamStats($matchId): mixed
    {
        return $this->_request('POST', '/business/match/match_team_stats', ['matchId' => $matchId]);
    }

    /**
     * 比赛分析
     * @param $matchId
     * @return mixed
     */
    public function getMatchAnalysis($matchId): mixed
    {
        return $this->_request('POST', '/business/match/match_analysis', ['matchId' => $matchId]);
    }

    /**
     * 比赛情报
     * @param $matchId
     * @return mixed
     */
    public function getMatchNews($matchId): mixed
    {
        return $this->_request('POST', '/business/match/match_news', ['matchId' => $matchId]);
    }

    /**
     * 获取比赛阵容中球员详情
     * @param $matchId
     * @param $playerId
     * @return mixed
     */
    public function getMatchPlayerStats($matchId, $playerId): mixed
    {
        return $this->_request('POST', '/business/match/match_player_stats', ['matchId' => $matchId, 'playerId' => $playerId]);
    }

    /**
     * 获取比赛表格
     * @param $matchId
     * @return mixed
     */
    public function getMatchTables($matchId): mixed
    {
        return $this->_request('POST', '/business/match/match_tables', ['matchId' => $matchId]);
    }

    /**
     * 获取资讯概览
     * @return array|false|mixed|stdClass
     */
    public function getArticleOverview(): mixed
    {
        return $this->_request('POST', '/business/manage/home/home_details_new', ['timezoneId' => 'GMT+8']);
    }

    /**
     * 获取资讯列表
     * @param $contentColumnId
     * @param $pageNum
     * @param int $pageSize
     * @return array|false|mixed|stdClass
     */
    public function getArticleList($contentColumnId, $pageNum, $pageSize = 30): mixed
    {
        return $this->_request('POST', '/business/manage/home/home_list', [
            'pageNum' => $pageNum,
            'pageSize' => $pageSize,
            'query' => [
                'contentColumnId' => $contentColumnId
            ]
        ]);
    }

    /**
     * 获取资讯详情
     * @param $contentId
     * @return array|false|mixed|stdClass
     */
    public function getArticleDetail($contentId): mixed
    {
        return $this->_request('POST', '/business/manage/home/information_details', ['contentId' => $contentId]);
    }

    /**
     * 获取专家排行榜
     * @param $numType
     * @param $rankType
     * @return array|false|mixed|stdClass
     */
    public function getExpertRank($numType, $rankType): mixed
    {
        return $this->_request('POST', '/business/expert/rank', ['numType' => $numType, 'rankType' => $rankType]);
    }

    /**
     * 获取网关
     * @return mixed|string
     */
    private function _getGateway(): mixed
    {
        return $this->gatewayGroup[array_rand($this->gatewayGroup)];
    }

    /**
     * HTTP请求
     * @param mixed $method
     * @param mixed $api
     * @param mixed $data
     * @return array|false|mixed|stdClass
     */
    private function _request($method, $api, $data = []): mixed
    {
        $url = $this->_getGateway() . $api;
        if ($method == 'GET' && !empty($data)) {
            $url .= '?' . http_build_query($data);
        }
        $option = [
            'headers' => $this->headers,
            'http_errors' => false,
        ];
        if ($method == 'POST') {
            $option['body'] = new_json_encode($data);
        }
        try {
            //请求延迟 上次api返回非200时，延迟加倍
            $multiplication = $this->lastRequestHttpError ? $this->httpErrorDelayMultiplication : 1;
            if ($this->requestDelayTime * $multiplication) {
                if (Coroutine::inCoroutine()) {
                    \Swoole\Coroutine::sleep($this->requestDelayTime * $multiplication);
                } else {
                    usleep(intval($this->requestDelayTime * $multiplication * 1000 * 1000));
                }
            }
            $this->lastRequestHttpError = false;

            $response = $this->client->request($method, $url, $option);
            $httpCode = $response->getStatusCode();
            if ($httpCode == 200) {
                return new_json_decode($response->getBody()->__toString());
            } else {
                $this->logger->warning(sprintf('%s %s httpCode=%d 延迟%d秒', $method, $url, $httpCode, $this->requestDelayTime * 5));
                $this->lastRequestHttpError = true;
            }
        } catch (GuzzleException $e) {
            $this->logger->warning(sprintf('%s %s error=%s', $method, $url, $e->getMessage()));
            Coroutine::sleep(1);
        }
        return false;
    }
}
